GRIDDATA
Overview
The GRIDDATA function performs multidimensional interpolation on unstructured (scattered) data points. Given a set of known data points with coordinates and corresponding values, it estimates values at new arbitrary locations. This is particularly useful when measurements are taken at irregular positions and need to be evaluated at different locations or mapped onto a regular grid.
This implementation wraps SciPy’s scipy.interpolate.griddata function from the SciPy library. The function supports three interpolation methods:
Nearest: Returns the value at the data point closest to each interpolation point. This method is fast and works in any number of dimensions, using the NearestNDInterpolator.
Linear (default): Tessellates the input points into N-dimensional simplices (triangles in 2D, tetrahedra in 3D) using Delaunay triangulation and performs linear interpolation within each simplex. See LinearNDInterpolator for details.
Cubic: For 1D data, uses cubic spline interpolation. For 2D data, uses the Clough-Tocher scheme, which produces a piecewise cubic, continuously differentiable (C1), and approximately curvature-minimizing surface. The cubic method is limited to 1D and 2D data.
The linear and cubic methods rely on the convex hull of the input points. For interpolation points outside this convex hull, the function returns a user-specified fill_value. The nearest method does not have this limitation and always returns the closest point’s value.
For smooth functions, the cubic method generally produces the most accurate results, while nearest neighbor is appropriate when preserving discrete values or when speed is critical. Linear interpolation offers a good balance between accuracy and computational cost.
This example function is provided as-is without any representation of accuracy.
Excel Usage
=GRIDDATA(points, values, xi, fill_value, griddata_method)
points(list[list], required): Data point coordinates (n_points, n_dims)values(list[list], required): Data point values (n_points, 1)xi(list[list], required): Points at which to interpolate (n_new_points, n_dims)fill_value(float, required): Value for points outside the convex hullgriddata_method(str, optional, default: “linear”): Interpolation method
Returns (list[list]): 2D list of interpolated values (n_new_points, 1), or error message (str) if invalid.
Examples
Example 1: Demo case 1
Inputs:
| points | values | xi | fill_value | ||
|---|---|---|---|---|---|
| 0 | 0 | 0 | 0.5 | 0.5 | 0 |
| 1 | 0 | 1 | |||
| 0 | 1 | 1 | |||
| 1 | 1 | 2 |
Excel formula:
=GRIDDATA({0,0;1,0;0,1;1,1}, {0;1;1;2}, {0.5,0.5}, 0)
Expected output:
| Result |
|---|
| 1 |
Example 2: Demo case 2
Inputs:
| points | values | xi | griddata_method | fill_value | ||
|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0.1 | 0.1 | nearest | 0 |
| 1 | 0 | 1 | ||||
| 0 | 1 | 2 |
Excel formula:
=GRIDDATA({0,0;1,0;0,1}, {0;1;2}, {0.1,0.1}, "nearest", 0)
Expected output:
| Result |
|---|
| 0 |
Example 3: Demo case 3
Inputs:
| points | values | xi | griddata_method | fill_value | ||
|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0.5 | 0.5 | cubic | -999 |
| 1 | 0 | 0 | ||||
| 0 | 1 | 0 | ||||
| 1 | 1 | 0 | ||||
| 0.5 | 0.5 | 1 |
Excel formula:
=GRIDDATA({0,0;1,0;0,1;1,1;0.5,0.5}, {0;0;0;0;1}, {0.5,0.5}, "cubic", -999)
Expected output:
| Result |
|---|
| 1 |
Example 4: Demo case 4
Inputs:
| points | values | xi | griddata_method | fill_value |
|---|---|---|---|---|
| 0 | 0 | 1.5 | linear | 0 |
| 1 | 1 | |||
| 2 | 4 |
Excel formula:
=GRIDDATA({0;1;2}, {0;1;4}, {1.5}, "linear", 0)
Expected output:
| Result |
|---|
| 2.5 |
Python Code
import numpy as np
from scipy.interpolate import griddata as scipy_griddata
def griddata(points, values, xi, fill_value, griddata_method='linear'):
"""
Interpolate unstructured D-D data.
See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.griddata.html
This example function is provided as-is without any representation of accuracy.
Args:
points (list[list]): Data point coordinates (n_points, n_dims)
values (list[list]): Data point values (n_points, 1)
xi (list[list]): Points at which to interpolate (n_new_points, n_dims)
fill_value (float): Value for points outside the convex hull
griddata_method (str, optional): Interpolation method Valid options: Linear, Nearest, Cubic. Default is 'linear'.
Returns:
list[list]: 2D list of interpolated values (n_new_points, 1), or error message (str) if invalid.
"""
def to2d(x):
return [[x]] if not isinstance(x, list) else x
def validate_and_convert(arr, name):
if not isinstance(arr, list):
return None, f"Invalid input: {name} must be a list."
if len(arr) == 0:
return None, f"Invalid input: {name} must not be empty."
try:
np_arr = np.array(arr, dtype=float)
except Exception as e:
return None, f"Invalid input: {name} could not be converted to numeric array. Details: {e}"
if np_arr.ndim != 2:
return None, f"Invalid input: {name} must be a 2D array."
return np_arr, None
# Normalize inputs to 2D lists
points = to2d(points)
values = to2d(values)
xi = to2d(xi)
# Validate and convert to numpy arrays
points_arr, error = validate_and_convert(points, "points")
if error:
return error
values_arr, error = validate_and_convert(values, "values")
if error:
return error
xi_arr, error = validate_and_convert(xi, "xi")
if error:
return error
# Validate method
valid_methods = ["linear", "nearest", "cubic"]
if not isinstance(griddata_method, str):
return "Invalid input: griddata_method must be a string."
if griddata_method not in valid_methods:
return f"Invalid input: griddata_method must be one of {valid_methods}."
# Validate fill_value
if not isinstance(fill_value, (int, float)):
return "Invalid input: fill_value must be numeric."
n_points = points_arr.shape[0]
n_dims = points_arr.shape[1]
# Validate minimum points for cubic method
if griddata_method == "cubic" and n_dims > 2:
return "Invalid input: cubic method only supports 1D and 2D data."
if griddata_method == "cubic" and n_dims == 2 and n_points < 4:
return "Invalid input: cubic method requires at least 4 points for 2D data."
if values_arr.shape[0] != n_points:
return f"Invalid input: points and values must have same number of rows (got {n_points} and {values_arr.shape[0]})."
if values_arr.shape[1] != 1:
return f"Invalid input: values must have exactly 1 column (got {values_arr.shape[1]})."
if xi_arr.shape[1] != n_dims:
return f"Invalid input: xi must have same number of columns as points (got {xi_arr.shape[1]} and {n_dims})."
# Flatten values for scipy.interpolate.griddata
values_flat = values_arr.flatten()
# Check for invalid values in input data
if np.any(np.isinf(points_arr)):
return "Invalid input: points contains infinite values."
if np.any(np.isinf(values_flat)):
return "Invalid input: values contains infinite values."
if np.any(np.isinf(xi_arr)):
return "Invalid input: xi contains infinite values."
# Perform interpolation
try:
result = scipy_griddata(
points_arr, values_flat, xi_arr, method=griddata_method, fill_value=fill_value
)
except Exception as e:
return f"scipy.interpolate.griddata error: {e}"
# Convert result to 2D list
if not isinstance(result, np.ndarray):
return "scipy.interpolate.griddata error: unexpected result type."
# Handle different result shapes
if result.ndim == 0:
# Scalar result (single point interpolation)
return [[float(result)]]
elif result.ndim == 1:
# Most common case: 1D array of interpolated values
return [[float(val)] for val in result]
else:
# Higher dimensional result, flatten it
result_flat = result.flatten()
return [[float(val)] for val in result_flat]